/*Prufer序列 应用
* 1.Prufer编码
    将一棵无根树转化为一个序列（即Prufer序列），
    另外Prufer序列也可以反过来转化为一棵树，
    即Prufer序列和树之间是一一对应的
 
* 2.凯莱定理
    一个无向完全图有 n^(n−2)棵生成树
    证明凯莱定理->证明有多少棵不同的生成树->证明有多少种Prufer序列
    Prufer序列共有 n−2 项，其范围为 1∼n，故其种类数为 n^(n−2)

* 3.Prufer算法
    假定 n 号节点为根，找到除根外度数最小的节点，在删除该节点之前，将其父节点输出，重复该流程，直到最后只剩下两个节点，
    即Prufer序列只有 n−2 个元素，因为Prufer序列最多 n−1 个元素，而最后一个元素一定为 n，所以这个元素可以省略，
    输出的元素即为Prufer序列

* 4.树-(线性时间)->Prufer序列
    假定当前出度为 0 且编号最小的节点为 j，则输出 fa[j]，
    删除 j 之后，出度为 0 的节点至多只会增加一个，即 fa[j]，
    判断删除 j 之后 fa[j] 的出度是否为 0，
        如果 fa[j] 的出度为 0 且 fa[j]<j 说明 fa[j] 是当前出度为 0 且编号最小的节点，递归输出这样的父节点即可，
        否则说明这样的 j 只会更大，即 j 只会增加，
    这样即可线性时间内将一颗树转化为Prufer序列

* 5.Prufer序列-(线性时间)->树
    先将 n 这个节点加入到Prufer序列中，Prufer序列中某个数出现的次数即为该数在树中的儿子节点的数量，
    从 1 开始找到儿子数量为 0 且编号最小的节点 j，其父节点即为当前遍历的Prufer序列的元素，将该元素从Prufer序列中删去，
    因为删除该元素后儿子数量为 0 的节点数量至多直接增加一个，
    如果该元素的儿子数量为 0 且编号小于 j，说明当前节点即为儿子数量为 0 且编号最小的节点，递归处理即可，
    这样的 j 同样也是递增的，
    故可以在线性时间内将一个Prufer序列转化为一棵树

* 本题:
    f[i][j]表示前i个点分成j个环的方案数，
    枚举1号所在环的环数，这样的环有C[k−1][i−1]种，
    环也有不同的种类，k点排列有k!，
    假定每次都是拿环上最上面的那个点连边，则显然有k种方案，即对应全排列，
    可以看成旋转操作形成的环是不同的，但是由于是无向图，对于某条边来说会连两次

    转移方程:
    f[i][j]=∑(k=1~i−j+1)f[i−k][j−1]×C[k−1][i−1]×k!/2
    则答案为 ∑(k=1~n)f[n][k]×n^(k−2)
    特判k=1时
    对于含n个点的环，这时显然不用向外连边，即这时的总方案应该为(n−1)/2
 */

#define DEBUG
#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include <iostream>
using namespace std;
#define int long long
const int N = 210, INF = 0x3f3f3f3f;

int n, MOD;
int C[N][N];
int g[N]; //g[k]=k!/2
int f[N][N]; //f[i][j]:把i个点分成j个环的方案数

void init() //预处理C[][], g[]
{
    for(int i=0; i<=n; i++)
        for(int j=0; j<=i; j++)
            if(!j) C[i][j]=1;
            else C[i][j] = (C[i-1][j-1]+C[i-1][j]) % MOD;

    g[1]=1, g[2]=0, g[3]=3; //g[3]已经/2
    for(int i=4; i<=n; i++) g[i]=g[i-1]*i%MOD;
}

signed main()
{
    #ifdef DEBUG
        freopen("./in.txt","r",stdin);
    #else
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    #endif

    cin >> n >> MOD;
    init();

    f[0][0]=1;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++)
            for(int k=1; k<=i-j+1; k++)
                f[i][j]=(f[i][j]+f[i-k][j-1]*C[i-1][k-1]*g[k]%MOD) % MOD;

    int res=g[n-1]; //统计总方案数，k=1时的方案数单独计算
    int p=1; //记录n^(k-2)
    for(int k=2; k<=n; k++)
    {
        res = (res + f[n][k]*p) % MOD;
        p=p*n%MOD;
    }
    cout << res << endl;
    return 0;
}